/* ------------------------------------------------------------------------*
 *
 * ------------------------------------------------------------------------*/
#include "bsp.h"
#include "stdint.h"
#include "os_obj.h"
#include "systask.h"

#include "nor_cmd.h"
#include "bsp_spi_nor.h"
#include "log_buff_manage.h"

#include "str_ext.h"
#include "common.h"
/*****************************************************************************
* @brief   delay .
*****************************************************************************/

void LogErase(uint32_t AddrBase);             /*从指定地址擦除，Nums指定擦除的扇区个数*/
void LogProgram(uint32_t Addr, uint8_t *Data, uint16_t Len); /*向指定指定地址编程数据*/
void LogRead(uint32_t Addr, uint8_t *Data, uint16_t Len);    /*读取块数据*/
void LogFlashFullCallBack(uint8_t mode); /*存满回调*/

// 日志数据
typedef struct
{
	sig_time_type time;
	uint16_t temp_pv;
	uint16_t temp_sv;
	uint16_t humi_pv;
	uint16_t humi_sv;
	uint16_t ver[24];
} log_dat_type;

log_dat_type log_dat;

// 日志缓存配置
log_buff_api_ref(log_buff_cfg);
log_buff_info_type log_buff_info;
log_buff_cfg_type  log_buff_cfg =
{
	.buff_amount = 4,
	.first_base = 256 * 1024,
	.buff_size = 32 * 1024,
	.sector_size = 4 * 1024,
	.ext_page_size = 2 * 1024,
	.data_size = 48,
	.p_data = (uint8_t*)&log_dat,
	.info = &log_buff_info,
	.erase = LogErase,
	.program = LogProgram,
	.read = LogRead,
	.full_callback = LogFlashFullCallBack,
	.api = log_buff_api_name(log_buff_cfg)
};
log_buff_api_make(log_buff_cfg);

// 日志缓存管理
typedef struct
{
	int32_t search_res;
	sig_time_type sig_time;
	TIME_Type rtc_time;
	log_dat_type log_rd;
	uint16_t save_req;
	uint16_t read_req;
	uint8_t clr_req;
	uint8_t alain_req;
	int8_t tm_search_req;
	uint8_t hd_search_req;
	uint8_t init_req;
} log_buff_test_type;

log_buff_test_type log_buff_obj;

/*-----------------------------------------------------------------------------------------------------*
* log_buff_test
*-----------------------------------------------------------------------------------------------------*/
void log_buff_test(void)
{
	gd25_dbg_puts("switch to log buffer test module \n");

	// 设置时间
	rtc_time_run_sec(&log_buff_obj.rtc_time, 30);
	rtc_time_run_min(&log_buff_obj.rtc_time, 360);
	rtc_time_run_hour(&log_buff_obj.rtc_time, 15*366*24);

	log_buff_init(&log_buff_cfg);

	if (log_buff_cfg.info->site_next > 0)
	{
		log_buff_read(&log_buff_cfg, log_buff_cfg.info->site_next - 1, &log_dat);
	}

	for (;;)
	{
		if(sys_st.str_module != 3)
			break;
		
		osDelay(ms_ticks(10));

		// 清除日志缓存
		if (log_buff_obj.clr_req)
		{
			LogErase(log_buff_cfg.info->flash_base);
			LogErase(log_buff_cfg.info->flash_base + 4 * 1024);
			LogErase(log_buff_cfg.info->flash_base + 8 * 1024);
			log_buff_init(&log_buff_cfg);
			log_buff_obj.clr_req = 0;
		}

		// 保存日志
		if (log_buff_obj.save_req)
		{
			log_buff_obj.save_req--;
			rtc_time_run_min(&log_buff_obj.rtc_time, 2);
			log_dat.time = time_to_sig(&log_buff_obj.rtc_time);
			log_dat.temp_pv = (log_dat.temp_pv + 3) & 0x7FF;
			log_dat.humi_pv = (log_dat.humi_pv + 5) & 0x3FF;
			log_buff_save(&log_buff_cfg);
		}

		// 读取一条日志
		if(log_buff_obj.read_req)
		{
			log_buff_cfg.api->read(log_buff_obj.read_req, &log_buff_obj.log_rd);
			log_buff_obj.read_req = 0;
		}
		
		// 日志对齐
		if (log_buff_obj.alain_req)
		{
			log_buff_obj.alain_req = 0;
			log_buff_align(&log_buff_cfg);
		}

		// 初始化
		if (log_buff_obj.init_req)
		{
			log_buff_obj.init_req = 0;
			log_buff_init(&log_buff_cfg);
		}

		// 搜索
		if (log_buff_obj.tm_search_req)
		{
			NOP1();
			if(log_buff_obj.tm_search_req  < 0)
				log_buff_obj.search_res = log_buff_time_search(&log_buff_cfg, log_buff_obj.sig_time, -1);
			else
				log_buff_obj.search_res = log_buff_time_search(&log_buff_cfg, log_buff_obj.sig_time, 1);
			log_buff_obj.tm_search_req = 0;
			
			if(log_buff_obj.search_res >= 0)
			log_buff_obj.read_req = log_buff_obj.search_res;
			
			gd25_dbg_print("log buff search res: 0x%x \n", log_buff_obj.search_res);
		}
		
		if(log_buff_obj.hd_search_req)
		{
			log_buff_cfg.api->head_search(log_buff_obj.hd_search_req, (void *)&log_buff_obj.search_res);
			log_buff_obj.hd_search_req = 0;
		}
	}
}

/*--------------------------------------------------------------------------------*
* log buff hal
*---------------------------------------------------------------------------------*/
void LogProgram(uint32_t Addr, uint8_t *Data, uint16_t Len)
{
	SYS_UnlockReg();
	FMC_Open();
	FMC_ENABLE_AP_UPDATE();

	Len /= 4;
	while (Len--)
	{
		FMC_Write(Addr, *(uint32_t*)Data);
		Addr += 4;
		Data += 4;
	}

	FMC_DISABLE_AP_UPDATE();
	FMC_Close();
	SYS_LockReg();
}

void LogRead(uint32_t Addr, uint8_t *Data, uint16_t Len)
{
	Len /= 4;

	while (Len--)
	{
		*(uint32_t*)Data = inpw(Addr);;
		Addr += 4;
		Data += 4;
	}
}

void LogErase(uint32_t AddrBase)
{
	int index;

	SYS_UnlockReg();
	FMC_Open();
	FMC_ENABLE_AP_UPDATE();

	for (index = 0; index < 4 * 1024 / FMC_FLASH_PAGE_SIZE; index++)
	{
		FMC_Erase(AddrBase + index * FMC_FLASH_PAGE_SIZE);
	}

	FMC_DISABLE_AP_UPDATE();
	FMC_Close();
	SYS_LockReg();
}

void LogFlashFullCallBack(uint8_t mode)
{
	gd25_dbg_print("log buffer full call back \n");
}
